package com.stox.indicator;

import java.util.List;

import lombok.Data;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.stox.dto.Bar;
import com.stox.dto.BarValue;
import com.stox.indicator.MACD.Configuration;
import com.stox.indicator.MACD.Unit;

@Component
public class MACD implements Indicator<Configuration,Unit>{

	@Data
	public static class Unit{
		private double macd;
		private double signal;
		private double hist;
	}
	
	public static enum BackingMA{
		Simple,
		Exponential;
	}
	
	@Data
	public static class Configuration{
		private BarValue barValue = BarValue.CLOSE;
		private BackingMA averageType = BackingMA.Simple;
		private int longerSpan = 26;
		private int shorterSpan = 12;
		private int signalSpan = 9;
	}

	@Autowired
	private ExponentialMovingAverage exponentialMovingAverage;
	
	@Autowired
	private SimpleMovingAverage simpleMovingAverage;
	
	@Override
	public Configuration createDefaultConfiguration() {
		return new Configuration();
	}

	@Override
	public Unit getValue(Configuration configuration, List<Bar> bars, int index) {
		throw new UnsupportedOperationException();
	}

	@Override
	public Double[] getValues(Configuration configuration, Double[] values){
		throw new UnsupportedOperationException();
	}
	
	@Override
	public Unit[] getValues(Configuration configuration, List<Bar> bars) {
		Unit[] result = new Unit[bars.size()];
		Double[] longerMAs;
		Double[] shorterMAs;
		Double[] macd = new Double[result.length];
		Double[] signal;
		AbstractMovingAverage movingAverage = null;
		if(configuration.getAverageType().equals(BackingMA.Simple)){
			movingAverage = simpleMovingAverage;
		}else{
			movingAverage = exponentialMovingAverage;
		}
		
		AbstractMovingAverage.Configuration conf = movingAverage.createDefaultConfiguration();
		conf.setBarValue(configuration.getBarValue());
		conf.setSpan(configuration.getShorterSpan());
		shorterMAs = movingAverage.getValues(conf, bars);
		conf.setSpan(configuration.getLongerSpan());
		longerMAs = movingAverage.getValues(conf, bars);
		for(int index = 0; index < macd.length; index++){
			Double shorterMA = shorterMAs[index];
			Double longerMA = longerMAs[index];
			if(null != shorterMA && null != longerMA){
				macd[index] = shorterMA - longerMA;
			}
		}
		conf.setSpan(configuration.getShorterSpan());
		signal = movingAverage.getValues(conf, macd);
		for(int index = 0; index < macd.length; index++){
			if(null != macd[index] && null != signal[index]){
				Unit unit = new Unit();
				result[index] = unit;
				unit.setMacd(macd[index]);
				unit.setSignal(signal[index]);
				unit.setHist(macd[index] - signal[index]);
			}
		}
		
		return result;
	}
	
}
